//-*-C++-*-
/***************************************************************************
 *
 *   Copyright (C) 2024 by Willem van Straten
 *   Licensed under the Academic Free License version 2.1
 *
 ***************************************************************************/

// dspsr/Signal/General/dsp/DedispersionPipe1.h

#ifndef __dspsr_DedispersionPipe_h
#define __dspsr_DedispersionPipe_h

#include "Reference.h"

namespace dsp {

  class SingleThread;
  class TimeSeries;

  class PlasmaResponse;
  class Dedispersion;
  class Derotation;

  class InverseFilterbank;
  class InverseFilterbankResponse;
  class Filterbank;
  class Convolution;

  class Response;
  class ResponseProduct;
  class Apodization;
  class RFIFilter;
  class SampleDelay;

  //! Implements the dedispersion part of a pipeline
  class DedispersionPipe
  {

  public:

    //! Configuration parameters
    class Config;

    //! Set the configuration to be used in prepare and run
    void set_configuration (Config*);

    //! Constructor
    DedispersionPipe (Config* config = 0);

    //! Destructor
    ~DedispersionPipe ();

    //! Set the pipeline into which this pipe will integrate itself
    void set_pipeline(SingleThread*);

    //! Create the pipe and add it to the pipeline
    /*! \param input TimeSeries
        \retval output TimeSeries
    */
    TimeSeries* construct(TimeSeries* input);

    //! Finish preparing
    void prepare ();

    //! The dedispersion and/or derotation kernel
    Reference::To<PlasmaResponse> kernel;

    //! The dedispersion kernel
    Reference::To<Dedispersion> dedisp;

    //! The derotation kernel
    Reference::To<Derotation> derotate;

    //! Configuration parameters
    Reference::To<Config> config;

    //! Integrates the passband
    Reference::To<Response> passband;

    //! The frequency response applied during convolution
    Reference::To<Response> frequency_response;

    //! Optional window applied in time domain before forward FFT
    Reference::To<Apodization> temporal_apodization;

    //! Optional window applied in frequency domain before backward FFT
    Reference::To<Apodization> spectral_apodization;

    //! Creates the filterbank
    Reference::To<Filterbank> filterbank;

    //! reference to inverse filterbank
    Reference::To<InverseFilterbank> inverse_filterbank;

    //! The response of the inverse filterbank
    Reference::To<InverseFilterbankResponse> inverse_filterbank_response;

    //! Performs coherent dedispersion
    Reference::To<Convolution> convolution;

    //! An RFI mask that can be applied during dedispersion
    Reference::To<RFIFilter> rfi_filter;

    //! The product of the RFIFilter and Dedispersion kernel
    Reference::To<ResponseProduct> response_product;

    //! Removes inter-channel dispersion delays
    Reference::To<SampleDelay> sample_delay;

    //! The pipeline into which this pipe will integrate itself
    Reference::To<SingleThread> pipeline;

    //! Construct an inverse filterbank
    TimeSeries* construct_inverse_filterbank (TimeSeries*);

    //! Construct a filterbank
    TimeSeries* construct_filterbank (TimeSeries*);

    //! Construct a convolution operation
    TimeSeries* construct_convolution (TimeSeries*);

    //! Construct interchannel dispersive delay correction operation
    TimeSeries* construct_interchan (TimeSeries*);

    template<class CompositePipeline>
    void prepare(CompositePipeline* composite);
  };

}

#endif // !defined(__DedispersionPipe_h)
